---@class RedRob.ClientBattle
local ClientBattle = RedRob.CreateSingleton("ClientBattle")
local this = ClientBattle
function ClientBattle.Start(mapId,x,y,battleType)
    Util.WriteToFileAsync("report.txt",os.date("%Y-%m-%d %H:%M:%S",os.time()) ,false)
    Util.WriteToFileAsync("report.txt",logicMgr.HeroManager.GetRoleId(),true)
    Util.WriteToFileAsync("report.txt",logicMgr.DarkStreetMgr.resCountInWeek,true)
    if this.isStart then
        this.OnDestroy()
    end
    this.OnCreate(mapId)
    FireEvent(RedRob.Config.Event.BattleLoadingStart,battleType)
    local path = "Prefabs/MapPref/"..this.SCENE_NAME
    RedRob.SceneMgr.LoadScene(path,function()
        RedRob.CameraController.SetCameraPos(x,y)
        --RedRob.ActorManager.CreateMy(x,y)
        FireEvent(RedRob.Config.Event.BattleReady,battleType)
        RedRob.BattleMsgHandler.ReqSceneLoadOver()
    end)
end
function ClientBattle.Leave()

    this.OnDestroy()
    FireEvent(RedRob.Config.Event.BattleLeave)
end

function ClientBattle.OnCreate(mapId)
    this.isStart = true
    this.PLAYER_SCALE = 0.8
    this.SCENE_ORIGIN_POS = Vector3.New(-1.22,-0.01,-6.34)
    this.SCENE_ORIGIN_ROTATE_X = 40
    this.SCENE_NAME = "AutoFightMap19"
    this.LIMIT_MIN_X = 0 --左
    this.LIMIT_MAX_X = 40 --右
    this.LIMIT_MAX_Y = 9 --上
    this.LIMIT_MIN_Y = 0 --下
    this.FightStartWaitingDuring = 4.25
    local cfg = dataTable.getDataTableByStringId("t_mapdarklane",mapId)
    if cfg then
        this.LIMIT_MAX_X = cfg.size[1]
        this.LIMIT_MAX_Y = cfg.size[2]
        this.SCENE_ORIGIN_ROTATE_X = cfg.f_camara_x/100
        this.SCENE_ORIGIN_POS:Set(cfg.f_Coordinates[1],cfg.f_Coordinates[2],cfg.f_Coordinates[3])
        this.SCENE_NAME = cfg.f_Name
    else
        logError("找不到地图t_mapdarklane "..mapId)
    end
    this.isBattleFinished = false
    UnityEngine.Physics.autoSimulation = true
    this.StartUpdateTime()
    this.AddEvent()
    this.updateCallbackList = {}
    this.lateUpdateCallbackList = {}
    this.closeTime = 0  --结束时间戳秒
    this.waitingTime = 0 --等待战斗开启倒计时 戳秒
    this.openTime = 0   --开始时间戳秒
    this._battleTimeStart = HelperFunc.GetServerTime()
    this._TimeDelta = this._battleTimeStart - os.time()
    this._battleTime = this._battleTimeStart
    this.frameCount = 0
    this.deltaTime = 0
    this.isRoomDestroy = false
    RedRob.ActorManager.OnCreate()
    RedRob.PoolMgr.OnCreate()
    RedRob.KeyController.OnCreate()
    RedRob.SceneMgr.OnCreate()
    RedRob.CameraController.OnCreate()
    RedRob.AiMgr.OnCreate()
    RedRob.EffectMgr.OnCreate()
    RedRob.ReportMgr.OnCreate()
    RedRob.GameMode.OnCreate()
    RedRob.BufferMgr.OnCreate()
end
function ClientBattle.OnDestroy()
    if not this.isStart then
        return
    end
    this.isStart = false
    RedRob.ActorManager.OnDestroy()
    RedRob.KeyController.OnDestroy()
    RedRob.CameraController.OnDestroy()
    RedRob.AiMgr.OnDestroy()
    RedRob.SceneMgr.OnDestroy()
    RedRob.EffectMgr.OnDestroy()
    RedRob.ReportMgr.OnDestroy()
    RedRob.GameMode.OnDestroy()
    RedRob.BufferMgr.OnDestroy()
    --PoolMgr保证在最后释放
    RedRob.PoolMgr.OnDestroy()
    this.RemoveEvent()
    this.EndUpdateTime()
    this.updateCallbackList = nil
    this.lateUpdateCallbackList = nil
    UnityEngine.Physics.autoSimulation = false
    loginHandler.R_LeaveUnionWar()
end
function ClientBattle.AddEvent()
    ListenEvent(RedRob.Config.Event.ActorPosChanged,this.Event_ActorPosChange)
end
function ClientBattle.RemoveEvent()
    CloseEvent(RedRob.Config.Event.ActorPosChanged,this.Event_ActorPosChange)
end

function ClientBattle.RegisterUpdateCallback(callback,tb)
    for k,v in pairs(this.updateCallbackList) do
        if v.callback == callback and v.tb == tb then
            return
        end
    end
    table.insert(this.updateCallbackList,{callback = callback,tb = tb})
end
function ClientBattle.RegisterLateUpdateCallback(callback,tb)
    for k,v in pairs(this.lateUpdateCallbackList) do
        if v.callback == callback and v.tb == tb then
            return
        end
    end
    table.insert(this.lateUpdateCallbackList,{callback = callback,tb = tb})
end
function ClientBattle.IsInBattle()
    return this.isStart
end
---@return number,number,number
function ClientBattle.WorldToLocal(x,y,z)
    return RedRob.SceneMgr.InverseTransformPoint(x,y,z)
end
---@return number,number,number
function ClientBattle.LocalToWorld(x,y,z)
    return RedRob.SceneMgr.TransformPoint(x,y,z)
end
---@return number,number,number
function ClientBattle.WorldToScreenPoint(x,y,z)
    return RedRob.CameraController.WorldToScreenPoint(x,y,z)
end
function ClientBattle.LimitPos(x,y,z)
    if x > this.LIMIT_MAX_X then
        x = this.LIMIT_MAX_X
    elseif x < this.LIMIT_MIN_X then
        x = this.LIMIT_MIN_X
    end
    if y > this.LIMIT_MAX_Y then
        y = this.LIMIT_MAX_Y
    elseif y < this.LIMIT_MIN_Y then
        y = this.LIMIT_MIN_Y
    end
    z = 0
    return x,y,z
end
function ClientBattle.GetLimitRandomPos()
    local x = math.random(this.LIMIT_MIN_X,this.LIMIT_MAX_X)
    local y = math.random(this.LIMIT_MIN_Y,this.LIMIT_MAX_Y)
    return x,y,0
end
function ClientBattle.IsBattleWaiting()
    return this.waitingTime > 0.0001
end

function ClientBattle.IsBattleClose()
    return not this.IsBattleWaiting() and this.GetBattleTime() >= this.closeTime
end
function ClientBattle.GetMinX()
    return this.LIMIT_MIN_X
end
function ClientBattle.GetMaxX()
    return this.LIMIT_MAX_X
end
function ClientBattle.GetMinY()
    return this.LIMIT_MIN_Y
end
function ClientBattle.GetMaxY()
    return this.LIMIT_MAX_Y
end
function ClientBattle.GetWaitingTime()
    return this.waitingTime
end
function ClientBattle.GetBattleTime()
    return this._battleTime
end
function ClientBattle.IsFightStart()
    return not this.IsBattleWaiting() and this._battleTime - this.openTime  > this.FightStartWaitingDuring
end
function ClientBattle.InitBattleTime(closeTime,countdownTime,openTime)
    this.closeTime = tonumber(tostring(closeTime/1000))
    if countdownTime > 0 then
        this.waitingTime = countdownTime + this._battleTime
    else
        this.waitingTime = 0
    end
    this.openTime = tonumber(tostring(openTime/1000))
    FireEvent(RedRob.Config.Event.BattleTimeInit)
end
function ClientBattle.Update()
    this.frameCount = this.frameCount + 1
    local dt = Time.deltaTime
    this.deltaTime = dt
    this._battleTime = os.time() + this._TimeDelta
    RedRob.ReportMgr.Record(this.frameCount,dt)
    if this.closeTime > 0 and not this.isBattleFinished and this._battleTime > this.closeTime then
        this.isBattleFinished = true
        FireEvent(RedRob.Config.Event.BattleTimeOut)
    end
    --update
    for k,v in pairs(this.updateCallbackList) do
        if v.tb then
            v.callback(v.tb,dt)
        else
            v.callback(dt)
        end
    end
    --late update
    for k,v in pairs(this.lateUpdateCallbackList) do
        if v.tb then
            v.callback(v.tb,dt)
        else
            v.callback(dt)
        end
    end

end
function ClientBattle.StartUpdateTime()
    this.EndUpdateTime()
    this.updateTimerId = utimer.frameCall(this.Update,-1)
end
function ClientBattle.EndUpdateTime()
    if this.updateTimerId then
        utimer.remove(this.updateTimerId)
        this.updateTimerId = nil
    end
end

function ClientBattle.SameVector(v1,v2) --z不管了
    if not v1 or not v2 then
        return false
    end
    return math.abs(v1.x - v2.x) < 0.00001 and math.abs(v1.y - v2.y) < 0.00001
end
function ClientBattle.GetBattleStage()
    local BattleStage = RedRob.Config.BattleStage
    local stage = BattleStage.close
    local remainTime = 0
    local wait = this.GetWaitingTime() - this.GetBattleTime()
    if wait > 0 then
        stage = BattleStage.waiting
        remainTime = wait
    elseif this.closeTime > 0 then
        stage = BattleStage.battle
        remainTime = this.closeTime - this.GetBattleTime()
    elseif HelperFunc.GetServerTime() >= this.closeTime then
        stage = BattleStage.close
    end
    return stage,remainTime

end

function ClientBattle.Event_ActorPosChange(actor)
    RedRob.ActorManager.NotifyActorPosChange()
    RedRob.CameraController.NotifyActorPosChange(actor)
end
